/*---------------------------------------------------------------------------------------------------------*/
/*                                                                                                         */
/* Copyright (c) Nuvoton Technology Corp. All rights reserved.                                             */
/*                                                                                                         */
/*---------------------------------------------------------------------------------------------------------*/
#include "Driver\DrvUSB.h"
#include "HID_ISP.h"
#include "prog.h"

#define MASS_BUFFER_SIZE        48              /* Mass Storage command buffer size */
#define STORAGE_BUFFER_SIZE     512             /* Data transfer buffer size in 512 bytes alignment */
#define	UDC_SECTOR_SIZE		    512             /* logic sector size */

#define VENDOR_ID               0x0250
#define PRODUCT_ID              0x0250

#define  CONFIG_0				0x03000000ul
#define  CONFIG_1               0x03000004ul
//uint32_t g_u32FlashSize;	              /* current device flash size */
//uint8_t  g_u8SecurityLockBit = 0x2;       /* security bit status */
uint32_t g_u32FlashBaseAddress = 0;       /* when loader run in APROM, it's LDROM_BASE, in LDROM it's 0*/
uint32_t g_u32DataBaseAddress = 0;      /* data flash base address */

/* DATA Flash Programming API */
//extern void DataFlashRead(uint32_t addr, uint32_t buffer);
extern void FMC_ReadPage(uint32_t u32startAddr, uint32_t * u32buff);
extern void DataFlashWrite(uint32_t addr, uint32_t buffer);

/* USB flow control variables */
uint8_t g_u8UsbState;
uint8_t g_u8Address;
uint8_t g_u8Config;
uint8_t g_u8Flag;

/* CBW/CSW variables */
//struct CBW g_sCBW;
//struct CSW g_sCSW;

//======================================================
const uint8_t HidDeviceDescriptor[LEN_DEVICE] =
{
	LEN_DEVICE,		    // bLength
	DESC_DEVICE,	    // bDescriptorType
	0x00, 0x02,		    // bcdUSB  2.0
	0x00,			    // bDeviceClass
	0x00,			    // bDeviceSubClass
	0x00,			    // bDeviceProtocol
	MAX_PACKET_SIZE0,	// bMaxPacketSize0
	(VENDOR_ID & 0xFF), 
	(VENDOR_ID >> 8),   // idVendor
	(PRODUCT_ID & 0xFF), 
	(PRODUCT_ID >> 8),  // idProduct
	0x00, 0x01,		    // bcdDevice  0.1
	0x01,			    // iManufacture
	0x02,			    // iProduct
	0x03,			    // iSerialNumber
	0x01			    // bNumConfigurations
};

const uint8_t HidConfigurationBlock[LEN_CONFIG+LEN_INTERFACE+LEN_HID+LEN_ENDPOINT*2] =
{
	LEN_CONFIG,		                                        // bLength
	DESC_CONFIG,	                                        // bDescriptorType
	(LEN_CONFIG+LEN_INTERFACE+LEN_HID+LEN_ENDPOINT*2), 0x00,// wTotalLength
	0x01,			                                        // bNumInterfaces
	0x01,			                                        // bConfigurationValue
	0x00,			                                        // iConfiguration
	0xC0,			                                        // bmAttributes	  Bus Powered
	0x64,			                                        // MaxPower 100mA

/* const BYTE cbyInterfaceDescriptor[LEN_INTERFACE] = */
	LEN_INTERFACE,	// bLength
	DESC_INTERFACE,	// bDescriptorType
	0x00,			// bInterfaceNumber
	0x00,			// bAlternateSetting
	0x02,			// bNumEndpoints
	0x03,			// bInterfaceClass		 HID
	0x00,			// bInterfaceSubClass: 1=BOOT, 0=no boot
	0x00,			// bInterfaceProtocol: 0=none, 1=keyboard, 2=mouse
	0x00,			// iInterface

/* const BYTE cbyHidDescriptor[LEN_HID] = */
    LEN_HID,		// Size of this descriptor in UINT8s.
    DESC_HID,		// HID descriptor type.
    0x00, 0x02, 	// HID Class Spec. release number.
    0x00,			// H/W target country.
    0x01,			// Number of HID class descriptors to follow.
    DESC_HID_RPT,	// Dscriptor type.
    // Total length of report descriptor.
    HID_REPORT_DESCRIPTOR_SIZE & 0x00FF,
    (HID_REPORT_DESCRIPTOR_SIZE & 0xFF00) >> 8,

/* const BYTE cbyEndpointDescriptor1[LEN_ENDPOINT] = */
	LEN_ENDPOINT,	        // bLength
	DESC_ENDPOINT,	        // bDescriptorType
	0x81,			        // bEndpointAddress
	EP_INT,		        	// bmAttributes
	MAX_PACKET_SIZE, 0x00,	// wMaxPacketSize
	0x01,			        // bInterval

/* const BYTE cbyEndpointDescriptor2[LEN_ENDPOINT] = */
	LEN_ENDPOINT,	        // bLength
	DESC_ENDPOINT,	        // bDescriptorType
	0x01,			        // bEndpointAddress
	EP_INT,		        	// bmAttributes
	MAX_PACKET_SIZE, 0x00,	// wMaxPacketSize
	0x01			        // bInterval
};

const uint8_t HidReportDescriptor[HID_REPORT_DESCRIPTOR_SIZE] =
{
    0x05, 0x8c, // USAGE_PAGE (Generic Desktop)
    0x09, 0x01, // USAGE (0)
    0xa1, 0x01, // COLLECTION (Application)
	0x09, 0x01, //     USAGE(01)
    0x15, 0x00, //     LOGICAL_MINIMUM (0)
    0x25, 0xff, //     LOGICAL_MAXIMUM (255)
    0x95, MAX_PACKET_SIZE, //     REPORT_COUNT (8)
    0x75, 0x08, //     REPORT_SIZE (8)
    0x81, 0x02, //     INPUT (Data,Var,Abs)
	0x09, 0x02, //     USAGE(02)
    0x91, 0x02, //     OUTPUT (Data,Var,Abs)
    0xc0        // END_COLLECTION
};

const uint8_t LangID[4] =
{
	4,				// bLength
	DESC_STRING,	// bDescriptorType
	0x09, 0x04
};

const uint8_t ManufactureString[14] =
{
	14,				// bLength
	DESC_STRING,	// bDescriptorType
	'l', 0, 'x', 0, 'y', 0, 'p', 0, 'p', 0, 'c', 0
};

const uint8_t ProductString[16] =
{
	16,				// bLength
	DESC_STRING,	// bDescriptorType
	'H', 0, 'i', 0, 'd', 0, ' ', 0, 'I', 0, 'S', 0, 'P', 0
};
/*
const uint8_t SerialString[16] =
{
	16,				// bLength
	DESC_STRING,	// bDescriptorType
	'H', 0, 'I', 0, 'D', 0, '0', 0, '0', 0, '0', 0, '0', 0
};
*/
const uint8_t* const Strings[] = 
{
	LangID,
	ManufactureString,
	ProductString,
	ProductString,
};

void RoughDelay(uint32_t t)
{
    volatile int32_t delay;

    delay = t;

    while(delay-- >= 0);
}

void my_memcpy(void *dest, const void *src, int32_t size)
{
    int32_t i;

    for (i = 0; i < size; i++)
       *((uint8_t *)dest + i) = *((uint8_t *)src + i);
}

//======================================================
// USB Configuration
//======================================================
void UsbCfg(void)
{
    /* Init the USB device address to 0x0 */
    outp32(&USBD->FADDR, 0x00);

    /* Init control end point */
	USBD->BUFSEG.BUFSEG = 0x1F;						 		/* Buffer for setup packet */
    _DRVUSB_SET_CFG_EP0(EPT_CFGP);					  		/* Clear EP0 CTRL IN Ready Flag */
    _DRVUSB_SET_CFG(0, CFG0_SETTING);				   		/* EP0 ==> control IN end point, address 0 */
    _DRVUSB_SET_EP_BUF(0, USB_SRAM_BASE + BUF0_SETTING);	/* Buffer for EP0 */
    _DRVUSB_SET_CFG_EP1(EPT_CFGP);						   	/* Clear EP1 CTRL OUT Ready Flag */
    _DRVUSB_SET_CFG(1, CFG1_SETTING);					  	/* EP1 ==> control OUT end point, address 0 */
    _DRVUSB_SET_EP_BUF(1, USB_SRAM_BASE + BUF1_SETTING);  	/* Buffer for EP1 */
    
    /* Init Interrput IN end point */
	_DRVUSB_SET_CFG_EP2(EPT_CFGP);				 			/* Clear EP2 INT IN Ready Flag */
	_DRVUSB_SET_CFG(EP_INT_IN, CFG2_SETTING);			  			/* EP2 ==> Bulk IN end point, address 1 */
	_DRVUSB_SET_EP_BUF(EP_INT_IN, USB_SRAM_BASE + BUF_INT_IN); 		/* Buffer for EP2 (INT IN) */	
	
	/* Init Interrput OUT end point */
	_DRVUSB_SET_CFG_EP3(EPT_CFGP);			  				/* Clear EP3 INT OUT Ready Flag */
	_DRVUSB_SET_CFG(EP_INT_OUT, CFG3_SETTING);		  				/* EP3 ==> Bulk OUT end point, address 1 */
	_DRVUSB_SET_EP_BUF(EP_INT_OUT, USB_SRAM_BASE + BUF_INT_OUT);		/* Buffer for EP3 (INT OUT) */
	
	g_u8Address = 0;    /* Device address */
	g_u8Config = 0;
	g_u8Flag = 0;       /* Flag to record the USB request */
}

//======================================================
// USB Floating Detect
//======================================================
void UsbFdt(void)
{
	uint8_t u8FLDET = USBD->FLDET.FLDET;

	_DRVUSB_SET_EVENT_FLAG(INTSTS_FLDET);
	    
    if (u8FLDET)
	{
	    /* USB Plug In */
	
		if (g_u8UsbState & USB_STATE_ATTACHED)
		{
		    /* Do nothing if it is already attached */
			return;
		}
		
		/* Update USB state */
		g_u8UsbState = USB_STATE_ATTACHED;
		
		/* Init the end points */
		UsbCfg();
		
	    /* Enable USB and enable PHY */
        _DRVUSB_ENABLE_USB();
	}
	else
	{
	    /* USB Un-plug */
	
	    /* Update USB state */
		g_u8UsbState = USB_STATE_DETACHED;
		
	    /* Disable USB, Disable remote weak up, and disable PHY */
        _DRVUSB_DISABLE_USB();
	}
}


//======================================================
// USB Bus Event
//======================================================
void UsbBus(void)
{
	uint8_t u8ATTR = *((__IO uint32_t *)(&USBD->ATTR)) & 0xFF;
	uint8_t u8UsbState;

    /* Clear event flag */
	_DRVUSB_SET_EVENT_FLAG(INTSTS_BUS);
	
	u8UsbState = g_u8UsbState;
    
    /* Just return if USB detached. */
    if (u8UsbState == USB_STATE_DETACHED)
		return;

    /* Process USB bus command if USB is attached. */
	if (u8ATTR & ATTR_USBRST)
	{	
	    /* Enable USB and enable PHY */
        _DRVUSB_ENABLE_USB();		
		
		/* Enter default state */
        u8UsbState = USB_STATE_DEFAULT;
		
		/* Configure the end-points */
		UsbCfg();
	}
	else if (u8ATTR & ATTR_SUSPEND)
	{	
	    /* Enable USB but disable PHY */
        _DRVUSB_DISABLE_PHY();
		
		/* Update the USB state */
        u8UsbState |= USB_STATE_FLAG_SUSPENDED;
	}
	else if (u8ATTR & ATTR_RESUME)
	{
	    /* Enable USB and enable PHY */
		_DRVUSB_ENABLE_USB();
		
		/* Clear the suspend state */
        u8UsbState &= ~USB_STATE_FLAG_SUSPENDED;
	}

    g_u8UsbState = u8UsbState;
}


//======================================================
int32_t UsbStdReq(void)
{
	int volatile len, idx;
    uint8_t tmp[8];
    
    my_memcpy(tmp, g_au8UsbSetup, 8);
    
	/* check if after DEFAULT state (RESET) */
	if ((g_u8UsbState & USB_STATE_FLAG_DEFAULT) == 0x00)
		return FALSE;

	/* parse the request in setup packet */	
    switch (tmp[1])
	{
		case GET_DESCRIPTOR:
		{
			len = tmp[6] + ((uint32_t)tmp[7] << 8);
            
			switch (tmp[3])
            {
				// Get Device Descriptor
				case DESC_DEVICE:
				{
					if (len > LEN_DEVICE)
					    len = LEN_DEVICE;

                    my_memcpy(g_au8UsbCtrl, (void *)HidDeviceDescriptor, len);
					if(devParam->flag != VALID_FLAG){
						// if there is no param for this device, set there is no serial number
						((uint8_t*)g_au8UsbCtrl)[sizeof(HidDeviceDescriptor)-2] = 0;
					}
					break;
				}
				// Get Configuration Descriptor
				case DESC_CONFIG:
				{
					if (len > HidConfigurationBlock[2])
					    len = HidConfigurationBlock[2];
					
					my_memcpy(g_au8UsbCtrl, (void *)HidConfigurationBlock, len);                   
                    break;
				}
				// Get String Descriptor
				case DESC_STRING:
				{
					// Get Language
					uint8_t i = tmp[2];
					switch(i){
						case INITIAL_PROG:
						{
						 	progState = PS_Initial;
							_DRVUSB_TRIG_EP(EP_INT_OUT, 64);
							break;
						}
						case CONFIG_PROG:
						{
							progState = PS_Config;
							_DRVUSB_TRIG_EP(EP_INT_OUT, 64);
							break;
						}
						case RESET2APROM:
					    {
							/* Boot from AP */
					        FMC->ISPCON.BS = 0;
							progState = PS_Reset;
							_DRVUSB_TRIG_EP(EP_INT_OUT, 64);
							break;    
						}
						case RESET2LDROM:
					    {
							/* Boot from LD */
					        FMC->ISPCON.BS = 1;
							progState = PS_Reset;
							_DRVUSB_TRIG_EP(EP_INT_OUT, 64);
							break;
						}
					}
					if(i >= sizeof(Strings)/sizeof(Strings[0])){
					 	i = sizeof(Strings)/sizeof(Strings[0]) - 1;
					}
					//if(len > Strings[i][0]){
						len = Strings[i][0];
					//}
					if( (devParam->flag == VALID_FLAG) && i == 3){
						uint16_t* pBuf = (uint16_t*)g_au8UsbCtrl;
						//uint32_t idx;
						*pBuf ++ = 	((DESC_STRING<<8) | ((2+sizeof(devParam->sn))) );
						my_memcpy(pBuf,devParam->sn,20);
						//for(idx = 0; idx < 8;idx++){
						//	*pBuf = 0;
						//	*pBuf++ = devParam->sn[idx];
						//}
						len = ((2+sizeof(devParam->sn)));//g_au8UsbCtrl[0];
						break;
					}
					my_memcpy(g_au8UsbCtrl, (void *)Strings[i], len);
                    break;
				}
				// Get Hid Descriptor,
				case DESC_HID:
				{
					//
					if (len > LEN_HID)
					    len = LEN_HID;
					if(((PUsbRequest_t)tmp)->USBwIndex0 == 0){
						my_memcpy(g_au8UsbCtrl, (void *)(HidConfigurationBlock+LEN_CONFIG+LEN_INTERFACE), len);
						break;
					}                   
                    return FALSE;
				}
				// Get Report Descriptor
				case DESC_HID_RPT:
				{
					//
					if (len > HID_REPORT_DESCRIPTOR_SIZE)
					    len = HID_REPORT_DESCRIPTOR_SIZE;
					if(((PUsbRequest_t)tmp)->USBwIndex0 == 0){
						my_memcpy(g_au8UsbCtrl, (void *)HidReportDescriptor, len);                   
	                    break;
					}                   
                    return FALSE;
				}
				default:
					return FALSE;
			}
			_DRVUSB_SET_CFG(0, DATA1 (CFG0_SETTING));
			_DRVUSB_TRIG_EP(0, len);
			g_u8Flag = FLAG_OUT_ACK;
			return TRUE;
		}
		case SET_ADDRESS:
		{
		    /* Accept set address command only before USB configured */
			if ((g_u8UsbState & USB_STATE_FLAG_CONFIGURED) == 0)
			{
				/* Get the device address */
				g_u8Address = tmp[2];
                
				_DRVUSB_SET_CFG(0, DATA1 (CFG0_SETTING));
				_DRVUSB_TRIG_EP(0, 0);
				g_u8Flag = FLAG_SET_ADDRESS;
				return TRUE;
			}
			return FALSE;
		}
		case SET_CONFIGURATION:
		{
			g_u8Config = tmp[2];
            
			_DRVUSB_SET_CFG(0, DATA1 (CFG0_SETTING));
			_DRVUSB_TRIG_EP(0, 0);
			g_u8Flag = FLAG_SET_CONFIG;
			return TRUE;
		}
		case CLEAR_FEATURE:
		case SET_FEATURE:
		{	
			_DRVUSB_SET_CFG(0, DATA1 (CFG0_SETTING));
			_DRVUSB_TRIG_EP(0, 0);
			return TRUE;
		}
		case GET_CONFIGURATION:
		{
			g_au8UsbCtrl[0] = g_u8Config;
            
			_DRVUSB_SET_CFG(0, DATA1(CFG0_SETTING));
			_DRVUSB_TRIG_EP(0, 1);
			g_u8Flag = FLAG_OUT_ACK;
			return TRUE;
		}
		case GET_STATUS:
		{
            uint8_t u8Data;

            u8Data = tmp[0];
			// Device
			if (u8Data == 0x80)
            	g_au8UsbCtrl[0] = 1;	// Self-Powered
			
			// Interface
			else if (u8Data == 0x81)
            	g_au8UsbCtrl[0] = 0;
			
			// Endpoint
			else if (u8Data == 0x82)
            {
                uint32_t u32CfgAddr;
                u8Data = tmp[4];
                u32CfgAddr = ((u8Data & 0xF) << 4) + USBD_CFGP0;

				g_au8UsbCtrl[0] = (inp32(u32CfgAddr) >> 1) & 1;
			}
			else
				return FALSE;
   			
            g_au8UsbCtrl[1] = 0;

			_DRVUSB_SET_CFG(0, DATA1 (CFG0_SETTING));
			_DRVUSB_TRIG_EP(0, 1);
			g_u8Flag = FLAG_OUT_ACK;
			return TRUE;
		}
		case GET_INTERFACE:
		{
			g_au8UsbCtrl[0] = 0;

			_DRVUSB_SET_CFG(0, DATA1(CFG0_SETTING));
			_DRVUSB_TRIG_EP(0, 1);
			g_u8Flag = FLAG_OUT_ACK;
			return TRUE;
		}
		case SET_INTERFACE:
		{
			g_u8Flag = FLAG_SET_INTERFACE;

			_DRVUSB_SET_CFG(0, DATA1(CFG0_SETTING));
			_DRVUSB_TRIG_EP(0, 0);
			return TRUE;
		}
		default:
			return FALSE;
	}
}


//======================================================
int32_t UsbClassReq(void)
{
    uint8_t tmp[8];

    my_memcpy(tmp, g_au8UsbSetup, 8);
	switch(tmp[1])
    {
		// HID Specify report
		case GET_REPORT:
		// get report request
		{
			break;
		}
		case SET_REPORT:
		// set report request
		{
			if(tmp[3] == HID_RPT_TYPE_INPUT){
				_DRVUSB_TRIG_EP(1, 0);
			}else if(tmp[3] == HID_RPT_TYPE_OUTPUT){
				_DRVUSB_TRIG_EP(1, 0);
			}else if(tmp[3] == HID_RPT_TYPE_FEATURE){
				_DRVUSB_TRIG_EP(1, 0);
			}else{
				// Unknown request
		        _DRVUSB_CLEAR_EP_READY_AND_TRIG_STALL(0);
		        _DRVUSB_CLEAR_EP_READY_AND_TRIG_STALL(1);
			}
			return TRUE;
		}
		case GET_PROTOCOL:
		{
			break;
		}
		case SET_PROTOCOL:
		{
			_DRVUSB_SET_EP_TOG_BIT(0, FALSE);
    		_DRVUSB_TRIG_EP(0, 0x00);
			return TRUE;
		}
		//case GET_IDLE:
		//{
		//	break;
		//}
		case SET_IDLE:
		{
			_DRVUSB_SET_EP_TOG_BIT(0, FALSE);
    		_DRVUSB_TRIG_EP(0, 0x00);
			return TRUE;
		}
	}
	return FALSE;
}


//======================================================
int32_t UsbSetup(void)
{
    /* Clear the data IN/OUT ready flag of control end-points */
	_DRVUSB_SET_CFG_EP0(CFGP_CLRRDY);	
    _DRVUSB_SET_CFG_EP1(CFGP_CLRRDY);
	
	/* USB device request in setup packet: offset 0, D[6..5]: 0=Stardard, 1=Class, 2=Vendor, 3=Reserved */
	switch (g_au8UsbSetup[0] & 0x60)
	{
		case REQ_STANDARD:
			return UsbStdReq();
		case REQ_CLASS:
			return UsbClassReq();
		default:
			return FALSE;
	}
}


//======================================================
void UsbInAck(void)
{

    switch (g_u8Flag)
	{
		// Out ACK
		case FLAG_OUT_ACK:
			_DRVUSB_TRIG_EP(1, 0);
			break;
		// Set Address
		case FLAG_SET_ADDRESS:
		{
			if (g_u8Address == 0)
				g_u8UsbState = USB_STATE_DEFAULT;
			else
				g_u8UsbState = USB_STATE_ADDRESS;
			
            outp32(&USBD->FADDR, g_u8Address);
			break;
		}
		// Set Interface
		case FLAG_SET_INTERFACE:
		// Set Configuration
		case FLAG_SET_CONFIG:
		{
			if (g_u8Config == 0)
				g_u8UsbState = USB_STATE_ADDRESS;
			else
			{
				g_u8UsbState = USB_STATE_CONFIGURED;
				// ---------------------------------
				_DRVUSB_SET_CFG(2, DATA0 (CFG2_SETTING));
				_DRVUSB_TRIG_EP(3, 31);
				// ---------------------------------
			}
			break;
		}
		default:
			return;
	}
	g_u8Flag = 0;
}

//======================================================

__inline void UsbOutAck(void)
{
}
/*
void UsbBulkInAck(void)
{
	//_DRVUSB_TRIG_EP(2, 64);
	if(progState == PS_Pending){
		progState = PS_Done;
	}
}
*/
void   SendData(const uint8_t* data)
{
   	my_memcpy(g_au8UsbIntIn,data,64);
	progState = PS_Pending;
	_DRVUSB_TRIG_EP(EP_INT_IN, 64);
}

//======================================================
void UsbBulkOutAck(void)
{
    uint32_t data[16];
	my_memcpy(data,g_au8UsbIntOut,64);
	_DRVUSB_TRIG_EP(EP_INT_OUT, 64);
	OnRecvData(data);
	//return TRUE;
}


//======================================================
// USB USB Event
//======================================================
void UsbUsb(uint32_t u32INTSTS)
{
	uint32_t u32STS = _DRVUSB_GET_EPSTS();

	if (u32INTSTS & INTSTS_SETUP)
	{	
	    /* Clear setup event */
		_DRVUSB_SET_EVENT_FLAG(INTSTS_SETUP);	
		if (!UsbSetup())
		{	
		    /* Setup error, stall the device */
			_DRVUSB_SET_CFGP(0, (CFGP_SSTALL | CFGP_CLRRDY));
			_DRVUSB_SET_CFGP(1, (CFGP_SSTALL | CFGP_CLRRDY));
		}
	}
	else if(u32INTSTS & INTSTS_EPTF0)
	{	
	    /* Ctrl In */
		_DRVUSB_SET_EVENT_FLAG(INTSTS_EPTF0);
		UsbInAck();
	}
	else if(u32INTSTS & INTSTS_EPTF1)
	{	
	    /* Ctrl Out */
		_DRVUSB_SET_EVENT_FLAG(INTSTS_EPTF1);
		UsbOutAck();
	}
	else if(u32INTSTS & INTSTS_EPTF2)
	{	
	    /* Bulk In */
		_DRVUSB_SET_EVENT_FLAG(INTSTS_EPTF2);
		if(progState == PS_Pending){
			progState = PS_Done;
		}
		//UsbBulkInAck();
	}
	else if(u32INTSTS & INTSTS_EPTF3)
	{
		//uint32_t data[16];
		_DRVUSB_SET_EVENT_FLAG(INTSTS_EPTF3);
		UsbBulkOutAck();	
		//my_memcpy(data,g_au8UsbIntOut,64);
		//_DRVUSB_TRIG_EP(EP_INT_OUT, 64);
		//OnRecvData(data);
	}
	else
	{	
        /* Unknow event */
		_DRVUSB_SET_EVENT_FLAG(INTSTS_USB); 
	}
}


void udcFlashInit(void)
{
    //uint32_t u32Addr = 0x4000;	  // 32K
    
    FMC->ISPCON.ISPEN = 1;
	FMC->ISPCON.LDUEN = 1;
#if 0
	if(FMC->ISPCON.BS){
		// run in LDROM
		outp32(FMC_ISPCMD, 0x00);   /* ISP Read */
    
	    /* To check APROM Size */
	    while (1)
	    {
	        outp32(FMC_ISPADR, u32Addr);
	        outp32(FMC_ISPTRG, 0x01);
	        __ISB();
	
	        if (FMC->ISPCON.ISPFF)
	        {
	            FMC->ISPCON.ISPFF = 1; 
	            break;    
	        }
	        else
	        {
	            u32Addr <<= 1;
	        }
	    }
	}else{
		// run in APROM
		/* enable loader rom update */
		FMC->ISPCON.LDUEN = 1;
		u32Addr = 0x1000;
	}
#endif
    //FMC->ISPCON.ISPEN = 0;
    
    /* Read Config0 value */
	//outp32(FMC_ISPCMD, 0x00);   /* ISP Read */
    //outp32(FMC_ISPADR, 0x300000);
    //outp32(FMC_ISPTRG, 0x01);
    //__ISB();
    
    //g_u8SecurityLockBit = inp32(FMC_ISPDAT) & BIT1;
    
    //g_u32FlashSize = u32Addr;
}
